﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PeoplesJukebox.Core.Interfaces;
using PeoplesJukebox.Core.MediaItems;
using PeoplesJukebox.Core.TrackLists.Bases;

namespace PeoplesJukebox.Core.TrackLists
{
    /// <summary>
    /// Tracklist based on user selection, queued in order of popularity
    /// </summary>
    public class SelectedTrackList : TrackListBase
    {
        private object syncLock = new object();
        private List<SelectedTrack> TrackList { get; set; } 

        /// <summary>
        /// Default constructor
        /// </summary>
        public SelectedTrackList() 
        {
            this.Reset();
        }

        /// <summary>
        /// Gets the name of the tracklist
        /// </summary>
        public override string Name
        {
            get { return "Selected"; }
        }

        /// <summary>
        /// Resets the queue of selected tracks
        /// </summary>
        public void Reset()
        {
            lock (syncLock)
            {
                TrackList = new List<SelectedTrack>();
            }
        }

        /// <summary>
        /// Adds a track to the queue
        /// </summary>
        /// <param name="trackId">Track ID to add</param>
        /// <returns>Whether track was added</returns>
        public bool AddTrack(int trackId)
        {
            SelectedTrack track = this.TrackList.Find(t => t.TrackId == trackId);
            if (track != null)
            {
                //if the track's already there, increment the vote count:
                track.SelectedCount++;
            }
            else
            {
                //otherwise add it:
                track = new SelectedTrack();
                track.TrackId = trackId;
                track.SelectedCount = 1;
                track.SelectedTime = DateTime.Now;
                lock (syncLock)
                {
                    TrackList.Add(track);
                }
            }
            return true;
        }

        /// <summary>
        /// Returns the number of queued tracks
        /// </summary>
        /// <returns>Queue size</returns>
        public int GetQueueSize()
        {
            return TrackList.Count;
        }

        /// <summary>
        /// Gets the ID of the next track to play
        /// </summary>
        /// <returns>Track ID</returns>
        protected override int GetNextTrackId()
        {
            int nextTrackId = -1;

            //get the track with the highest selection count, 
            //and the earliest selection date:
            var tracks = from track in TrackList
                    orderby track.SelectedCount descending, track.SelectedTime
                    select track.TrackId;

            nextTrackId = tracks.First();

            if (nextTrackId > -1)
            {
                //remove from the queue:
                lock (syncLock)
                {
                    TrackList.Remove(TrackList.Find(t => t.TrackId == nextTrackId));
                }
            }

            return nextTrackId;
        }

        /// <summary>
        /// Returns whether there are any selected tracks left
        /// </summary>
        public override bool HasTracks
        {
            get { return TrackList.Count > 0; }
        }

        /// <summary>
        /// Returns whether the tracklist allows repeat plays
        /// </summary>
        public override bool AllowsRepeatPlay
        {
            get { return true; }
        }

        private class SelectedTrack
        {
            public int TrackId { get; set; }
            public DateTime SelectedTime { get; set; }
            public int SelectedCount { get; set; }
        }
    }
}